﻿using System;
using System.Collections.Generic;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SpriteGame.Rendering;
using System.Xml.Serialization;


namespace SpriteGame
{
    [XmlInclude(typeof(BaseSprite))]
    [XmlInclude(typeof(ComplexShape))]
    [XmlInclude(typeof(CustomShape))]
    [XmlInclude(typeof(Ball))]
    public class BaseSprite: IDisposable
    {
        protected string texture;
        public String Texture
        {
            get { return texture; }
            set { texture = value; }
        }

        protected Scene parent;
        public Scene Parent
        {
            get { return parent; }
            set { parent = value; }
        }

        protected World world;
        public World World
        {
            get { return world; }
        }

        protected Vector2 startPos;
        public Vector2 StartPosition
        {
            get { return startPos; }
            set { startPos = value; }
        }

        protected float startRot;
        public float StartRot
        {
            get { return startRot; }
            set { startRot = value; }
        }

        protected Body body;

        protected float width = 0;
        public float Width
        {
            get { return width; }
        }
        protected float height = 0;
        public float Height
        {
            get { return height; }
        }

        bool canSave = true;
        public bool CanSave
        {
            get { return canSave; }
            set { canSave = value; }
        }

        protected bool isLoaded = false;
        public bool IsLoaded
        {
            get { return isLoaded; }
        }

        public Body Body
        {
            get { return body; }
        }

        BodyType bodyType;
        public BodyType BodyType
        {
            get { return bodyType; }
            set { bodyType = value; }
        }

        float mass = 0.1f;
        public float Mass
        {
            get { return mass; }
            set { mass = value; }
        }

        public virtual Vector2 Position
        {
            get { //return body.Position;
                return body.WorldCenter;
            }
            set { body.SetTransform(value, Rotation); }
        }

        public float Rotation
        {
            get { 
                return body.Rotation;
            }
        }

        bool hasCustomData = false;
        public bool HasCustomData
        {
            get
            {
                return hasCustomData;
            }
        }

        bool glow = false;

        public bool Glow
        {
            get { return glow; }
            set { glow = value; }
        }


        public BaseSprite() { }

        //The default empty constructor
        public BaseSprite(Scene _parent)
        {
            parent = _parent;
        }

      /*  public BaseSprite(Scene _parent, float _width, float _height, BodyType _type, Vector2 _position, float _rotation, String _texture)
        {
            parent = _parent;
            world = parent.World;

            texture = _texture;

            //body.
            width = _width;
            height = _height;

            float hx = width * 0.5f;
            float hy = height * 0.5f;
            Vertices box = PolygonTools.CreateRectangle(hx, hy);

            PolygonShape shape = new PolygonShape(box);

            body = world.CreateBody();
            body.SetTransform(ref _position, _rotation);
            body.BodyType = _type;
            Fixture fixture = body.CreateFixture(shape, 0.2f);

            //assign this entity to the physics body's tag, 
            //this means we can use the physics engine for visual culling
            //yay less work :D
            body.UserData = this;
        }*/

        public BaseSprite(Scene _parent, BodyType _type, Vector2 _position, float _rotation, String _texture)
        {
            bodyType = _type;
            texture = _texture;
            startPos = _position;
            startRot = _rotation;

            //this object was created at runtime, load it immediatly
            LoadContent(_parent);
        }

        public BaseSprite(Scene _parent, BodyType _type, Vector2 _position, float _rotation, float _mass, String _texture)
        {
            bodyType = _type;
            texture = _texture;
            startPos = _position;
            startRot = _rotation;

            //this object was created at runtime, load it immediatly
            LoadContent(_parent);
        }

        public BaseSprite(Scene _parent, BodyType _type, Vector2 _position, float _rotation, float _mass, String _texture, bool _latent)
        {
            bodyType = _type;
            texture = _texture;
            startPos = _position;
            startRot = _rotation;
            mass = _mass;
            //this object was created at runtime, load it immediatly
            //LoadContent(_parent);
        }

        /// <summary>
        /// Loads content from the buffer and assigns it to this entity
        /// note: entities created at runtime should be automatically loaded
        /// make sure you add the LoadContent method to custom constructors
        /// </summary>
        /// <param name="_parent">The parent scene</param>
        public virtual void LoadContent(Scene _parent)
        {
            parent = _parent;
            world = _parent.World;

            Texture2D tex = TextureLibrary.GetTexture(texture);

            //body.
            width = tex.Width * 0.07f;
            height = tex.Height * 0.07f;

            float hx = width * 0.5f;
            float hy = height * 0.5f;
            Vertices box = PolygonTools.CreateRectangle(hx, hy);

            PolygonShape shape = new PolygonShape(box);

            body = parent.World.CreateBody();
            body.SetTransform(ref startPos, startRot);
            body.BodyType = bodyType;
            Fixture fixture = body.CreateFixture(shape, mass);

            //assign this entity to the physics body's tag, 
            //this means we can use the physics engine for visual culling
            //yay less work :D
            body.UserData = this;
            isLoaded = true;
        }

        /// <summary>
        /// Updates the current entity
        /// </summary>
        /// <param name="_time"></param>
        public virtual void Update(GameTime _time)
        {

        }

        /// <summary>
        /// Pre physics calculation update
        /// </summary>
        public virtual void PrePhase()
        {

        }

        /// <summary>
        /// Post physics calculation update
        /// </summary>
        public virtual void PostPhase()
        {

        }

        public virtual void Dispose()
        {
            World.RemoveBody(body);
        }

        public virtual void Draw(ShapeRenderer _batch)
        {
            //_batch.DrawAnimatedQuad(18, 0, Position, Rotation, width, height, TextureLibrary.GetTexture(texture), false); 
            _batch.DrawQuad(Position, Rotation, width, height, TextureLibrary.GetTexture(texture)); 
        }
    }
}
